<template>
  <div class="fx-input-number" :class="{disabled,right,'no-input':!isInput}">
    <div class="less" v-if="isBtn" :class="[size,{disabled:min&&inputNumberValue<=min}]" @click="lessClick">
      <i class="iconfont icon-Less fs16"/>
    </div>
    <input type="number" v-model="inputNumberValue" :disabled="disabled" v-show="isInput"
           :style="{width: `${$attrs.width}px`}" :class="[size,{'is-btn':!isBtn}]"
           @blur="inputNumberBlur" @input="inputNumberBlur">
    <div class="plus" v-if="isBtn" :class="[size,{disabled:max&&inputNumberValue>=max}]" @click="plusClick">
      <i class="iconfont icon-plus fs16"/>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, inject, onMounted, PropType, ref, SetupContext, watch } from 'vue'
import { ComponentSize, componentSizeArr } from '@/base/types'
import { Emitter } from 'mitt'

interface InputNumberProps {
  modelValue: number;
  size: ComponentSize;
  disabled: boolean;
  step: number;
  max: number | null;
  min: number | null;
  right: boolean;
  isBtn: boolean;
  isInput: boolean;
}

export default defineComponent({
  name: 'FInputNumber',
  props: {
    // v-model
    modelValue: {
      type: Number as PropType<number>,
      default: 1
    },
    // 大小
    size: {
      type: String as PropType<ComponentSize>,
      default: 'default',
      validator (val: ComponentSize): boolean {
        return componentSizeArr.includes(val)
      }
    },
    // 禁用
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 步数
    step: {
      type: Number as PropType<number>,
      default: 1
    },
    // 最大
    max: {
      type: Number as PropType<number | null>,
      default: null
    },
    // 最小
    min: {
      type: Number as PropType<number | null>,
      default: null
    },
    // 控制器在右侧
    right: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 是否需要按钮
    isBtn: {
      type: Boolean as PropType<boolean>,
      default: true
    },
    // 是否需要输入框
    isInput: {
      type: Boolean as PropType<boolean>,
      default: true
    }
  },
  emits: ['update:modelValue', 'change'],
  setup (props: InputNumberProps, ctx: SetupContext) {
    // 当前数值
    const inputNumberValue = ref<number>(props.modelValue)
    // 记录有用的数据 当数据异常是返回正常数据
    let oldRightNumber = 0
    // 接收formItem mitt 监听器
    const formItemMitt = inject<Emitter['emit'] | undefined>('formItemMitt', undefined)
    // 处理 最大/最小 值
    const handleMaxMin = (): void => {
      if (props.min !== null && inputNumberValue.value <= props.min) {
        inputNumberValue.value = props.min
      }
      if (props.max !== null && inputNumberValue.value >= props.max) {
        inputNumberValue.value = props.max
      }
    }
    // 减少
    const lessClick = (): void => {
      if (props.disabled) return
      inputNumberValue.value -= props.step
      handleMaxMin()
    }
    // 增加
    const plusClick = (): void => {
      if (props.disabled) return
      inputNumberValue.value += props.step
      handleMaxMin()
    }
    // 失焦
    const inputNumberBlur = (): void => {
      if (Number.isNaN(Number(inputNumberValue.value))) {
        inputNumberValue.value = oldRightNumber
      }
      handleMaxMin()
    }

    watch(() => props.modelValue, (val: number): void => {
      inputNumberValue.value = val
    })
    watch(inputNumberValue, (val: number): void => {
      if (!Number.isNaN(Number(val))) oldRightNumber = val
      // 发送当前的数据给formItem
      if (formItemMitt) formItemMitt('formItemValue', inputNumberValue.value)
      ctx.emit('update:modelValue', Number(val))
      ctx.emit('change', Number(val))
    })

    onMounted(() => {
      // 发送当前的数据给formItem
      if (formItemMitt) formItemMitt('formItemValue', inputNumberValue.value)
    })

    return {
      inputNumberValue,
      lessClick,
      plusClick,
      inputNumberBlur
    }
  }
})
</script>
